use actix_web::{HttpResponse, ResponseError};
use deadpool_postgres::{CreatePoolError, PoolError};
use derive_more::{Display, From};
use std::num::TryFromIntError;
use std::time::SystemTimeError;
use tokio_pg_mapper::Error as PGMError;
use tokio_postgres::error::Error as PGError;

#[derive(Debug)]
pub struct UserNotExistsError {
    pub user_name: String,
}
impl std::fmt::Display for UserNotExistsError {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(formatter, "用户:{}不存在", self.user_name)
    }
}

#[derive(Debug)]
pub struct AuthError {
    pub message: String,
}
impl std::fmt::Display for AuthError {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(formatter, "{}", self.message)
    }
}
#[derive(Debug)]
pub struct UserNameDupError {
    pub user_name: String,
}
impl std::fmt::Display for UserNameDupError {
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(formatter, "用户名:{} 已存在", self.user_name)
    }
}

#[derive(Display, From, Debug)]
pub enum MyError {
    NotFound,
    IncorrectClientId,
    Msg(String),
    AuthError(AuthError),
    UserNotExists(UserNotExistsError),
    UserNameDup(UserNameDupError),
    PGError(PGError),
    PGMError(PGMError),
    PoolError(PoolError),
    CreatePoolError(CreatePoolError),
    SystemTimeError(SystemTimeError),
    TryFromIntError(TryFromIntError),
    ConfigError(config::ConfigError),
    RedisError(redis::RedisError),
}

impl std::error::Error for MyError {}

impl From<MyError> for std::io::Error {
    fn from(err: MyError) -> Self {
        std::io::Error::new(std::io::ErrorKind::Other, format!("{}", err))
    }
}
impl ResponseError for MyError {
    fn error_response(&self) -> HttpResponse {
        match *self {
            MyError::NotFound => HttpResponse::NotFound().finish(),
            MyError::RedisError(ref err) => {
                HttpResponse::InternalServerError().body(format!("RedisError:{}", err))
            }
            MyError::AuthError(_) => HttpResponse::Unauthorized().body(self.to_string()),
            MyError::UserNotExists(_) => HttpResponse::Unauthorized().body(self.to_string()),
            MyError::UserNameDup(_) => HttpResponse::NotAcceptable().body(self.to_string()),
            _ => HttpResponse::InternalServerError().body(self.to_string()),
        }
    }
}
